package com.example.itshome.network;

import android.app.Activity;
import android.content.Intent;
import android.util.Log;
import com.example.itshome.activity.LoginPageActivity;
import com.example.itshome.exception.RequestTokenLapsedException;
import com.example.itshome.exception.UsernameTokenOutSyncException;
import com.example.itshome.manager.UserInfoManager;
import com.example.itshome.util.SharePreferencesUtil;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public abstract class AbstractNetworkRequest{
    protected final static String DOMAIN_HOST="http://101.43.242.216:18950/";
    protected final static String GET_METHOD="GET";
    protected final static String POST_METHOD="POST";
    protected final static String IMAGES="images";
    private String requestMethod;
    private String token;
    protected final Activity activity;
    private Runnable handleResultRunnable;
    private Runnable handleExceptionRunnable;

    protected AbstractNetworkRequest setToken(String token) {
        this.token = token;
        return this;
    }

    private String getToken() {
        if(token==null){
            return UserInfoManager.getInstance().getTokenRequest();
        }
        return token;
    }

    protected void setRequestMethod(String requestMethod){
        this.requestMethod=requestMethod;
    }

    public AbstractNetworkRequest setHandleResultRunnable(Runnable handleResultRunnable) {
        this.handleResultRunnable = handleResultRunnable;
        return this;
    }

    public AbstractNetworkRequest setHandleExceptionRunnable(Runnable handleExceptionRunnable) {
        this.handleExceptionRunnable = handleExceptionRunnable;
        return this;
    }

    protected AbstractNetworkRequest(Activity activity){
        this(activity,POST_METHOD);
    }
    protected AbstractNetworkRequest(Activity activity, String method){
        requestMethod=method;
        this.activity= activity;
    }
    private HttpURLConnection getConnection(String pathAndParams, String requestMethod) throws IOException {
        HttpURLConnection connection;
        URL url;
        String params=null,path;
        Log.i("network",DOMAIN_HOST+pathAndParams);
        if(requestMethod.equals(GET_METHOD)){
            url=new URL(DOMAIN_HOST+pathAndParams);
        }else {
            int index=pathAndParams.indexOf('?');
            if(index!=-1){
                params=pathAndParams.substring(index+1);
                path=pathAndParams.substring(0,index);
            }else {
                path=pathAndParams;
            }
            url=new URL(DOMAIN_HOST+path);
        }
        connection= (HttpURLConnection) url.openConnection();
        connection.setRequestMethod(requestMethod);
        connection.setConnectTimeout(3000);
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        if(!(getToken()==null)){
            connection.setRequestProperty("Authorization",getToken());
        }
        if(requestMethod.equals(POST_METHOD)&&params!=null){
            connection.setDoOutput(true);
            OutputStream out= connection.getOutputStream();
            out.write(params.getBytes(StandardCharsets.UTF_8));
            out.flush();
            out.close();
        }

        return connection;
    }

    private String getResult() throws IOException, RequestTokenLapsedException {
        String pathAndParams= getPathAndParams();
        if(pathAndParams==null){
            throw new  IOException("缺少参数和路径");
        }
        HttpURLConnection connection=getConnection(pathAndParams,requestMethod);
        int code=connection.getResponseCode();
        if(code!=200&&code!=400){
            throw new IOException("返回码不为200:"+code);
        }
        String tokenRequest= connection.getHeaderField("Authorization-to-request");
        String tokenRefresh= connection.getHeaderField("Authorization-to-refresh");
        String lapsed=connection.getHeaderField("Lapsed");
        if(lapsed!=null){
            throw new RequestTokenLapsedException();
        }
        updateToken(tokenRequest,tokenRefresh);
        BufferedReader sr=new BufferedReader(new InputStreamReader(connection.getInputStream()));
        StringBuilder sb=new StringBuilder();
        String s;
        while ((s= sr.readLine())!=null){
            sb.append(s);
        }
        sr.close();
        return sb.toString();
    }

    protected abstract String getPathAndParams();
    protected abstract void handleResult(String result);
    protected boolean canStart(){
        return true;
    }
    protected void afterResult() {}
    protected void handleException(Exception exception){
        setHandleExceptionRunnable(new Runnable() {
            @Override
            public void run() {
                exception.printStackTrace();
            }
        });
    }

    public void start() {
        if(!canStart()){
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    String result = getResult();
                    Log.i("network",result);
                    handleCode(result);
                    handleResult(result);
                    if(handleResultRunnable!=null)
                    activity.runOnUiThread(handleResultRunnable);
                } catch (IOException e) {
                    handleException(e);
                    activity.runOnUiThread(handleExceptionRunnable);
                } catch (RequestTokenLapsedException e) {
                    e.printStackTrace();
                    if(UserInfoManager.getInstance().getTokenRefresh().equals(token)){
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Intent intent=new Intent(activity, LoginPageActivity.class);
                                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
                                activity.startActivity(intent);
                            }
                        });
                    }else {
                        setToken(UserInfoManager.getInstance().getTokenRefresh());
                        start();

                    }
                    return;
                }catch (UsernameTokenOutSyncException e){
                    e.printStackTrace();
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Intent intent=new Intent(activity, LoginPageActivity.class);
                            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
                            activity.startActivity(intent);
                        }
                    });
                    return;
                }
                afterResult();
            }
        }).start();
    }

    private void updateToken(String tokenRequest,String tokenRefresh){
        if(tokenRequest!=null){
            UserInfoManager.getInstance().setTokenRequest(tokenRequest);
            SharePreferencesUtil util=new SharePreferencesUtil(activity,SharePreferencesUtil.USERFile);
            util.putString("tokenRequest",tokenRequest);
        }

        if(tokenRefresh!=null){
            UserInfoManager.getInstance().setTokenRefresh(tokenRefresh);
            SharePreferencesUtil util=new SharePreferencesUtil(activity,SharePreferencesUtil.USERFile);
            util.putString("tokenRefresh",tokenRefresh);
        }
    }

    protected void handleCode(String result) throws UsernameTokenOutSyncException{
        try {
            JSONObject resultJson=new JSONObject(result);
            int code= resultJson.getInt("code");
            if(code==100){
                throw new UsernameTokenOutSyncException();
            }
        }catch (JSONException e){
            e.printStackTrace();
        }

    }
}
